﻿package 
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;	
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.ColorTransform;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.text.TextField;
	import org.papervision3d.cameras.Camera3D;
	import org.papervision3d.lights.PointLight3D;
	import org.papervision3d.materials.BitmapMaterial;
	import org.papervision3d.materials.shadematerials.CellMaterial;
	import org.papervision3d.materials.shadematerials.GouraudMaterial;
	import org.papervision3d.materials.WireframeMaterial;
	import org.papervision3d.objects.primitives.Sphere;
	import org.papervision3d.render.BasicRenderEngine;
	import org.papervision3d.scenes.Scene3D;
	import org.papervision3d.view.Viewport3D;
	
	/*
	 * coded by moka 2009 / 06/ 20 
	 * name : moka's MaterialBlendEffect
	 * extend : new material creation
	 */
	
	public class Main extends Sprite 
	{		
		private var scene:Scene3D;
		private var camera:Camera3D;
		private var viewport:Viewport3D;
		private var render:BasicRenderEngine;
		private var bmp:Bitmap;
		private var bmpBuffer:BitmapData;
		private var sphere:Sphere
		private var step:uint;
		private var info:TextField;
		private var infoArray:Array;
		
		// 貼圖的紋理
		[Embed(source = 'moka.gif')]
		private var EmbeddedImage:Class;
		private var image:Bitmap;		

		public function Main():void 
		{		
			// Class 類別隱式轉換成 Bitmap 類別
			image = new EmbeddedImage(); 
			
			// 設定場景不變形
			stage.scaleMode = "noScale"; 
			
			// Scene3D 用來組織場景母子關係樹狀架構
 			scene = new Scene3D();

			// Camera3D 為 3D 場景可視範圍設定
			camera = new Camera3D();
			
			// Viewport3D 用在呈現於 flash 場景(其類別繼承Sprite)
			viewport = new Viewport3D(640, 480);
			
			// 用以渲染 3D 場景之類別
			render = new BasicRenderEngine();
			
			// 用以繪製 viewport
			bmp = addChild(new Bitmap(new BitmapData(640, 480, true, 0)))as Bitmap;
			bmpBuffer = new BitmapData(640, 480);
			
			// 建立球體並改變球體網格
			
			sphere = scene.addChild(new Sphere(new GouraudMaterial(new PointLight3D), 150)) as Sphere;
			sphere.geometry.vertices[0].y = -300;
			sphere.geometry.vertices[sphere.geometry.vertices.length - 1].y = 300;		
			
			// 材質展示資訊
			infoArray = [
			"Step 1 : Bitmap 一般材質看起來較平無立體感",
			"Step 2 : Bitmap + Cell(toon) 一般 3D 遊戲常見卡通風格(塞路路)",
			"Step 3 : Bitmap + Cell(toon) + Gouraud 利用高登著色讓物件看起來更立體",
			"Step 4 : Bitmap + Cell(toon) + Gouraud + WireFrame 顯示 polygon"];
			info = addChild(new TextField()) as TextField;
			info.textColor = 0xFFCC00;
			info.width = 500;
			info.x = 100;
			info.text = "請點擊滑鼠 click stage to change material";			
			
			// 材質切換用
			step = 1;
			
			// 註冊事件
			stage.addEventListener(Event.ENTER_FRAME, onProcess);	
			stage.addEventListener(MouseEvent.MOUSE_DOWN, function onMouseDown():void {
				step = step++ % 4 + 1;
				info.text = infoArray[step - 1]
			});

			// Moka's work 2009
			(addChild(new TextField()) as TextField).htmlText = "<font color='#FFFFFF'>Moka's work 2009</font>"; 
		}		
		
		private function onProcess(e:Event):void {	
			sphere.rotationX = mouseX;
			sphere.rotationY = mouseY;
			
			// 渲染 3D 場景
			
			bmpBuffer.fillRect(bmpBuffer.rect, 0xFF333333);	
			
			for (var i:uint = 1 ; i <= 4; i++ ) {				
				switch(i)
				{
					case 1:
						sphere.material = new BitmapMaterial(image.bitmapData, true);
						render.renderScene(scene, camera, viewport);
						bmpBuffer.draw(viewport);
						break;	
					case 2:			
						sphere.material = new CellMaterial(new PointLight3D, 0xFFFFFF, 0, 3);
						render.renderScene(scene, camera, viewport);
						bmpBuffer.draw(viewport, new Matrix, new ColorTransform(0.5, 0.5, 0.5, 0.8), "hardlight");
						break;	
					case 3:
						sphere.material = new GouraudMaterial(new PointLight3D);
						render.renderScene(scene, camera, viewport);
						bmpBuffer.draw(viewport, new Matrix, new ColorTransform(0.8, 0.8, 0.8, 0.8), "hardlight");
						break;	
					case 4:
						sphere.material = new WireframeMaterial(0xFFCC00);
						render.renderScene(scene, camera, viewport);
						bmpBuffer.draw(viewport, new Matrix, new ColorTransform(0.1,0.1,0.1), "add");
				}
				if (i == step) break;
			}
			
			bmp.bitmapData.draw(bmpBuffer);
		}   
	}	
}